/*
 * NOTE: This copyright does *not* cover user programs that use HQ
 * program services by normal system calls through the application
 * program interfaces provided as part of the Hyperic Plug-in Development
 * Kit or the Hyperic Client Development Kit - this is merely considered
 * normal use of the program, and does *not* fall under the heading of
 * "derived work".
 * 
 * Copyright (C) [2004, 2005, 2006], Hyperic, Inc.
 * This file is part of HQ.
 * 
 * HQ is free software; you can redistribute it and/or modify
 * it under the terms version 2 of the GNU General Public License as
 * published by the Free Software Foundation. This program is distributed
 * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA.
 */

package features;

import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import org.snmp4j.CommandResponder;
import org.snmp4j.CommandResponderEvent;
import org.snmp4j.MessageDispatcherImpl;
import org.snmp4j.PDU;
import org.snmp4j.mp.MessageProcessingModel;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.SecurityLevel;
import org.snmp4j.security.SecurityModel;
import org.snmp4j.smi.Integer32;
import org.snmp4j.smi.OctetString;

import alarm.Alarm;
import alarm.AlarmRegistry;
import alarm.Event;

class SNMPSession_v2c extends SNMPSession_v1 {

	SNMPSession_v2c() {
		this.version = SnmpConstants.version2c;
	}

	public List<SNMPValue> getBulk(String name) throws SNMPException {
		// XXX optimize using snmp4j v2 specific stuff
		return super.getBulk(name);
	}

	public Map<String, SNMPValue> getTable(String name, int index) throws SNMPException {
		// XXX optimize using snmp4j v2 specific stuff
		return super.getTable(name, index);
	}

	public CommandResponder registerAlarm(final Alarm alarm, final CommandResponder commandResponder) throws SNMPException {
		try {
//			ResponseEvent resEvent = null;

			Event event = new Event();
			event.setDescription(new OctetString("Rising"));
			event.setCommunity(target.getCommunity());
			event.setOwner(alarm.getOwner());
			event.register(this);
			alarm.setRisingEventIndex(event.getEventIndex());
			
			event = new Event();
			event.setDescription(new OctetString("Falling"));
			event.setCommunity(target.getCommunity());
			event.setOwner(alarm.getOwner());
			event.register(this);
			alarm.setFallingEventIndex(event.getEventIndex());
			
			alarm.register(this);
			
			Timer timer = new Timer();
			long delay = alarm.getInterval().toInt() * 1000;
			TimerTask task = new TimerTask() {
				private final static int NONE = 0;
				private final static int FALLING = 1;
				private final static int RISING = 1;
				private final static String EVENT_INDEX_OID = ".1.3.6.1.2.1.16.9.2.1.1";
				
				private long lastFallingTime = -1;
				private long lastRisingTime = -1;
				
				@Override
				public void run() {
					if(AlarmRegistry.getInstance().isActive(alarm)) {
						try {
							int result = checkLog(alarm.getRisingEventIndex().toInt(), alarm.getFallingEventIndex().toInt());
							
							if(result != NONE) {
								final String msg;
								if(result == FALLING)
									msg = "discesa";
								else// if(result == RISING)
									msg = "salita";
								
								alarm.setAlarmValue(new Integer32(getSingleValue(Alarm.ALARMVALUE + "." + alarm.getVariableIndex().toInt()).toInt()));
								
								CommandResponderEvent commTmp = new CommandResponderEvent(
										new MessageDispatcherImpl(), 
										null, 
										target.getAddress(), 
										MessageProcessingModel.MPv2c, 
										SecurityModel.SECURITY_MODEL_ANY, 
										null, 
										SecurityLevel.NOAUTH_NOPRIV, 
										null, 
										new PDU(), 
										0, 
										null) {
									
									private static final long serialVersionUID = -2777335460818903022L;

									@Override
									public Object getSource() {
										return msg;
									}
								};
								
								commandResponder.processPdu(commTmp);
							}
								
						} catch (SNMPException e) {
							e.printStackTrace();
						}
					} else
						this.cancel();
				}
				
				private int checkLog(int risingEventIndex, int fallingEventIndex) throws SNMPException {
					List<SNMPValue> eventIndexes = getColumn(EVENT_INDEX_OID);
					List<SNMPValue> eventTimes = getColumn(EVENT_INDEX_OID);
					
					for (int i = 0; i < eventIndexes.size() && i < eventTimes.size(); i++) {
						long time = eventTimes.get(i).toLong();
						
						if(eventIndexes.get(i).toInt() == risingEventIndex) {
							if(time > lastRisingTime) {
								lastRisingTime = time;
								
								return RISING; 
							}
						}
						
						if(eventIndexes.get(i).toInt() == fallingEventIndex) {
							if(time > lastFallingTime) {
								lastFallingTime = time;
								
								return FALLING; 
							}
						}
					}
					
					return NONE;
				}
			};
			timer.schedule(task, delay, delay);
//			session.addCommandResponder(commandResponder);
		} catch (Exception exc) {
			exc.printStackTrace();

			throw new SNMPException("Impossibile registrare l'alarm", exc);
		}

		return commandResponder;
	}
}
